from BaseControl import BaseWebControl, WebFindKey
from Exeptions import ElementNotFoundException


class WebViewDelegateIndex(object):
    def __init__(self, parent=None, row=-1):
        super(WebViewDelegateIndex, self).__init__()
        self.parent = parent
        self.row = row

    def isValid(self):
        return self.row >= 0 and self.parent


class BaseWebViewLeafDelegate(BaseWebControl):
    def __init__(self, handler, index):
        super(BaseWebViewLeafDelegate, self).__init__(handler)
        self._index = index

    def children(self, timeoutSec=None, emptyIfTimeout=True):
        return []

    def childrenFor(self, predicate):
        return [child for child in self.children() if predicate(child)]

    def dataValue(self):
        return self.get_attribute("data-value")

    def index(self):
        return self._index

    def isLeaf(self):
        return bool(self.children())

    def isSelected(self):
        return self.get_attribute('class') == 'selecter-item selected'

    def setSelection(self, selection):
        def selector(driver):
            if selection != self.isSelected():
                self.click()
            return selection == self.isSelected()
        self.waitFor(selector, message="Unable to set selection for WebViewLeaf %s" % self.tag_name)


class BaseWebViewDelegate(BaseWebViewLeafDelegate):
    def __init__(self, handler, index, childrenBuilder):
        super(BaseWebViewDelegate, self).__init__(handler, index)
        self._childrenBuilder = childrenBuilder
        self._index = index

    def _childHandler(self):
        return WebFindKey.TAG_NAME, "li"

    def children(self, timeoutSec=None, emptyIfTimeout=True):
        children = []
        for row, child in enumerate(self.waitChildControls(*self._childHandler(), timeoutSec=timeoutSec,
                                                           emptyIfTimeout=emptyIfTimeout)):
            index = WebViewDelegateIndex(self, row)
            children.append(self._childrenBuilder.build(child, index))
        return children


class BaseWebViewDelegateBuilder(object):
    def __init__(self, rootDelegateCls=BaseWebViewDelegate, itemDelegateCls=BaseWebViewLeafDelegate):
        self.rootDelegateCls = rootDelegateCls
        self.itemDelegateCls = itemDelegateCls

    def build(self, controlHandler, index=WebViewDelegateIndex()):
        if not index.isValid():
            return self.rootDelegateCls(controlHandler, index, self)
        return self.itemDelegateCls(controlHandler, index)


class BaseWebView(BaseWebControl):
    def __init__(self, handler, delegateBuilder=BaseWebViewDelegateBuilder):
        super(BaseWebView, self).__init__(handler)
        self._delegateBuilder = delegateBuilder

    def columnsCount(self):
        return 1

    def deselectAll(self):
        self.transformItems(lambda x: True, lambda x: x.setSelection(False))

    def items(self, timeoutSec=None):
        return self.rootDelegate().children(timeoutSec)

    def itemsFor(self, predicate):
        return self.rootDelegate().childrenFor(predicate)

    def row(self, row):
        return self.items()[row]

    def rowsCount(self):
        return len(self.items(1))

    def rootDelegate(self):
        return self._delegateBuilder.build(self.obj(), WebViewDelegateIndex())

    def transformItems(self, selector, transformer):
        for item in self.itemsFor(selector):
            transformer(item)

    def hasItems(self, predicate):
        return bool(self.itemsFor(predicate))

    def hasItemsWithText(self, text):
        return self.hasItems(lambda x: x.text == text)

    def hasItemsWithDataValue(self, value):
        return self.hasItems(lambda x: x.dataValue == value)

    def selectedItems(self):
        return self.itemsFor(lambda x: x.isSelected())

    def selectItems(self, predicate):
        self.transformItems(lambda x: predicate(x) and not x.isSelected(), lambda x: x.setSelection(True))

    def selectItemsByText(self, value):
        try:
            self.selectItems(lambda x: x.text == value)
        except ElementNotFoundException as e:
            raise ElementNotFoundException("Element %s not found in %s" % (value, e.message))

    def selectItemsByDataValue(self, value):
        try:
            self.selectItems(lambda x: x.dataValue() == value)
        except ElementNotFoundException as e:
            raise ElementNotFoundException("Element %s not found in %s" % (value, e.message))
